package com.spooky.sync.note;

import java.util.LinkedList;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.DataSetObserver;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputFilter;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import com.spooky.sync.R;
import com.spooky.sync.note.dialog.TagSelectDialog;
import com.spooky.sync.note.model.EditorStorage;
import com.spooky.sync.persistence.dao.CategoryDAO;
import com.spooky.sync.persistence.dao.CategoryDAOBean;
import com.spooky.sync.persistence.dao.NoteDAO;
import com.spooky.sync.persistence.dao.NoteDAOBean;
import com.spooky.sync.persistence.entity.Category;
import com.spooky.sync.persistence.entity.Note;
import com.spooky.sync.persistence.entity.Tag;

public abstract class BaseEditorActivity extends Activity {
	private static final String TAG = BaseEditorActivity.class.getSimpleName();
	protected Note mNote;
	private List<Category> mCategories;
	private List<Tag> mTag;
	protected EditorStorage mEditorStorage;
	// GUI
	protected EditText mTextEditor;
	private CategorySpinner mCategorySpinner = null;
	protected AlertDialog mEditTitleDialog = null;
	private TagSelectDialog mTagSelectDialog = null;
	// TMP STORAGE
	private boolean mIsDynamicTitle = true;
	private String mCustomTitle = null;
	// BUNDLE KEY
	private static final String IS_DYNAMIC_TITLE_KEY = "mIsDynamicTitle";
	private static final String CUSTOM_TITLE_KEY = "mCustomTitle";

	public BaseEditorActivity() {
		mEditorStorage = EditorStorage.getInstance();
		mNote = mEditorStorage.getNote();
		mTag = mEditorStorage.getTag();
	}

	// Start menu
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.editor_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.editorSaveItem: {
			SaveNote saveNote = new SaveNote();
			saveNote.save();
			return true;
		}
		case R.id.editorTitleItem: {
			startChangeTitleDialog();
			return true;
		}
		case R.id.createCategoryItem: {
			return true;
		}
		case R.id.tagSelectItem: {
			startTagSelectDialog();
			return true;
		}
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void startTagSelectDialog() {
		if (mTagSelectDialog == null) {
			mTagSelectDialog = new TagSelectDialog(BaseEditorActivity.this);
		}
		if (!mTagSelectDialog.isShowing()) {
			mTagSelectDialog.setTags(mTag);
			mTagSelectDialog.show();
		}
	}

	private void onPauseTagSelectDialog() {
		if (mTagSelectDialog != null) {
			mEditorStorage.setTag(mTagSelectDialog.getTags());
			if (mTagSelectDialog.isShowing()) {
				mTagSelectDialog.dismiss();
			}
		}
	}

	// end menu
	// if(ChangeTitleDialog is open after orientation change)
	// not focus editText box and display ChangeTitleDialog with the same value
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (savedInstanceState != null) {
			mIsDynamicTitle = savedInstanceState.getBoolean(IS_DYNAMIC_TITLE_KEY, true);
			mCustomTitle = savedInstanceState.getString(CUSTOM_TITLE_KEY);
		}
		// Log.d(TAG, mContext.toString());
		mTextEditor = (EditText) findViewById(R.id.editor);
	}

	@Override
	protected void onSaveInstanceState(Bundle savedInstanceState) {
		savedInstanceState.putBoolean(IS_DYNAMIC_TITLE_KEY, mIsDynamicTitle);
		savedInstanceState.putString(CUSTOM_TITLE_KEY, mCustomTitle);
		super.onSaveInstanceState(savedInstanceState);
	}

	@Override
	protected void onPause() {
		super.onPause();
		stopChangeTitleDialog();
		stopCategorySpinner();
		onPauseTagSelectDialog();
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (mEditorStorage.isShowingEditTitle()) {
			startChangeTitleDialog();
		}
	}

	private void startChangeTitleDialog() {
		if (mEditTitleDialog == null) {
			mEditTitleDialog = new ChangeTitleDialog().create();
		}
		if (!mEditTitleDialog.isShowing()) {
			mEditTitleDialog.show();
		}
	}

	private void stopChangeTitleDialog() {
		if (mEditTitleDialog != null && mEditTitleDialog.isShowing()) {
			Log.d(TAG, "mEditTitleDialog.isShowing() == true");
			mEditTitleDialog.dismiss();
			mEditorStorage.setShowingEditTitle(true);
		} else {
			Log.d(TAG, "mEditTitleDialog.isShowing() == false");
			mEditorStorage.setShowingEditTitle(false);
		}
	}

	private void stopCategorySpinner() {
	}

	class ChangeTitleDialog extends AlertDialog.Builder {
		public ChangeTitleDialog() {
			super(BaseEditorActivity.this);
			final EditText mTitle = new EditText(BaseEditorActivity.this);
			TableLayout contentList = new TableLayout(BaseEditorActivity.this);
			contentList.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
			TableRow rowIsDynamicTitle = new TableRow(BaseEditorActivity.this);
			final CheckBox isDynamicTitle = new CheckBox(BaseEditorActivity.this);
			mTitle.setOnKeyListener(new OnKeyListener() {
				@Override
				public boolean onKey(View v, int keyCode, KeyEvent event) {
					Log.d(TAG, "onChangeTitle");
					if (mTitle.length() == 0) {
						isDynamicTitle.setChecked(true);
					} else {
						mCustomTitle = mTitle.getText().toString();
						isDynamicTitle.setChecked(false);
					}
					return false;
				}
			});
			mTitle.setSingleLine(true);
			mTitle.setFilters(new InputFilter[] { new InputFilter.LengthFilter(Note.MAX_TITLE_LENGTH) });
			mTitle.setText(mNote.getTitle());
			isDynamicTitle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
					Log.d(TAG, "onChangeIsDynamicTitle");
					mIsDynamicTitle = isChecked;
					if (isChecked) {
						if (!mTitle.isFocused()) {
							if (mTextEditor != null) {
								mTitle.setText(EditorUtil.getDynamicTitle(mTextEditor.getText().toString()));
							}
						}
					} else {
						mTitle.setText(mCustomTitle);
					}
				}
			});
			isDynamicTitle.setText("Dynamic");
			mCategorySpinner = new CategorySpinner();
			mCategorySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
				@Override
				public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) {
					try {
						mEditorStorage.setSelectedCategory(pos);
						mNote.setCategory(mCategories.get(pos));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				@Override
				public void onNothingSelected(AdapterView<?> adapterView) {
					try {
						mNote.setCategory(mCategories.get(0));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
			mCategorySpinner.setSelection(1);
			rowIsDynamicTitle.addView(isDynamicTitle);
			contentList.addView(mTitle);
			contentList.addView(rowIsDynamicTitle);
			contentList.addView(mCategorySpinner);
			setView(contentList);
			isDynamicTitle.setChecked(mIsDynamicTitle);
			setTitle("Change The Note Title");
			setPositiveButton("Confirm", new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Log.d(TAG, "onClickConfirm");
					if (mTitle.isFocused() && isDynamicTitle.isChecked()) {
						mNote.setTitle((String) EditorUtil.getDynamicTitle(mTextEditor.getText().toString()));
					} else {
						mNote.setTitle(mTitle.getText().toString());
					}
				}
			});
			setNegativeButton("Back", new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Log.d(TAG, "onClickBack");
					dialog.cancel();
				}
			});
			setCancelable(false);
		}
	}

	protected class CategorySpinner extends Spinner {
		public CategorySpinner() {
			super(BaseEditorActivity.this);
			new CategoryTask().execute();
		}

		private class CustomSpinnerAdapter implements SpinnerAdapter {
			@Override
			public int getCount() {
				return mCategories.size();
			}

			@Override
			public Object getItem(int pos) {
				return mCategories.get(pos);
			}

			@Override
			public long getItemId(int pos) {
				return mCategories.get(pos).getId();
			}

			@Override
			public int getItemViewType(int position) {
				return 0;
			}

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				TextView textView = new TextView(BaseEditorActivity.this);
				textView.setText(mCategories.get(position).toString());
				return textView;
			}

			@Override
			public int getViewTypeCount() {
				return 1;
			}

			@Override
			public boolean hasStableIds() {
				return true;
			}

			@Override
			public boolean isEmpty() {
				return mCategories.isEmpty();
			}

			@Override
			public void registerDataSetObserver(DataSetObserver observer) {
				// TODO Auto-generated method stub
			}

			@Override
			public void unregisterDataSetObserver(DataSetObserver observer) {
				// TODO Auto-generated method stub
			}

			@Override
			public View getDropDownView(int position, View convertView, ViewGroup parent) {
				if (convertView == null) {
					TextView textView = new TextView(BaseEditorActivity.this);
					textView.setText(mCategories.get(position).toString());
					convertView = textView;
				}
				return convertView;
			}
		}

		private class CategoryTask extends AsyncTask<String, Integer, List<Category>> {
			private CategoryDAO mCategoryDAO;

			@Override
			protected List<Category> doInBackground(String... params) {
				try {
					return mCategoryDAO.getAll();
				} catch (Exception e) {
				}
				return new LinkedList<Category>();
			}

			@Override
			protected void onCancelled() {
				super.onCancelled();
				mCategoryDAO.close();
			}

			@Override
			protected void onPostExecute(List<Category> result) {
				super.onPostExecute(result);
				if (result.size() == 0) {
					result.add(createDefault());
				}
				mCategoryDAO.close();
				mCategories = result;
				setAdapter(new ArrayAdapter<Category>(BaseEditorActivity.this, android.R.layout.simple_spinner_dropdown_item, result));
			}

			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				mCategoryDAO = new CategoryDAOBean(BaseEditorActivity.this);
			}

			@Override
			protected void onProgressUpdate(Integer... values) {
				super.onProgressUpdate(values);
			}

			private Category createDefault() {
				Category category = new Category();
				category.setCategory("Default");
				return mCategoryDAO.create(category);
			}
		}
	}

	protected static class EditorUtil {
		private static final String[] SPLITTERS = new String[] { "-", "_", "=", ".", ";", "|", ":", "/" };

		protected static CharSequence getDynamicTitle(final String text) {
			if (text == null || text.equals("")) {
				return "";
			}
			String truncatedText = null;
			if (text.length() > Note.MAX_TITLE_LENGTH) {
				truncatedText = text.substring(0, Note.MAX_TITLE_LENGTH);
			} else {
				truncatedText = text;
			}
			int pos = -1;
			for (String splitter : SPLITTERS) {
				pos = text.indexOf(splitter);
				if (pos != -1) {
					String substr = truncatedText.substring(0, pos).trim();
					return substr.length() >= 2 ? substr : truncatedText.trim();
				}
			}
			return truncatedText.trim();
		}
	}

	private class SaveNote {
		public void save() {
			assemble();
			if (verify()) {
				if (saveAction()) {
					back();
				}
			}
		}

		private boolean verify() {
			if (mNote.getTitle() == null || mNote.getTitle().length() <= 2) {
				Toast.makeText(BaseEditorActivity.this, R.string.editor_verify_title_short, Toast.LENGTH_LONG).show();
				return false;
			} else if (mNote.getText() == null || mNote.getText().length() <= 2) {
				Toast.makeText(BaseEditorActivity.this, R.string.editor_verify_text_short, Toast.LENGTH_LONG).show();
				return false;
			} else if (mNote.getCategory() == null || mNote.getCategory().getId() == null) {
				Toast.makeText(BaseEditorActivity.this, R.string.editor_verify_no_category, Toast.LENGTH_LONG).show();
				return false;
			}
			return true;
		}

		private void assemble() {
			try {
				mNote.setText(mTextEditor.getText().toString());
			} catch (Exception e) {
			}
			if (mNote.getCategory() == null) {
				try {
					mNote.setCategory(mCategories.get(0));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		private boolean saveAction() {
			NoteDAO noteDAO = null;
			try {
				noteDAO = new NoteDAOBean(BaseEditorActivity.this);
				if (mNote.getId() == null) {
					noteDAO.create(mNote);
					Toast.makeText(BaseEditorActivity.this, R.string.editor_verify_save, Toast.LENGTH_LONG).show();
				} else {
					noteDAO.update(mNote);
					Toast.makeText(BaseEditorActivity.this, R.string.editor_verify_update, Toast.LENGTH_LONG).show();
				}
				Note.clearEditorInstance();
				EditorStorage.resetInstance();
				return true;
			} catch (Exception e) {
				Toast.makeText(BaseEditorActivity.this, R.string.editor_unknown_error, Toast.LENGTH_LONG).show();
			} finally {
				Log.d(TAG, "finaly");
				noteDAO.close();
			}
			return false;
		}

		private void back() {
			BaseEditorActivity.this.finish();
		}
	}
}
